﻿using System;
using System.Linq;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.ComponentModel;
using System.Windows.Media;
using System.Windows.Input;
using System.Windows.Media.Animation;

namespace UBCon.Ribbon
{
    using UBCon.Ribbon.BaseControls;
    using UBCon.Ribbon.Interfaces;
    using System.Collections.Specialized;
    using System.Diagnostics;
    using UBCon.Ribbon.Models;
    using System.Windows.Controls.Primitives;
    using UBCon.Core.Enums;
    using System.Collections.Generic;
    using UBCon.Core;

    /// <summary>
    /// Represents list of tab items control.
    /// </summary>
    [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(RibbonTabItem))]
    [TemplatePart(Name = PART_RibbonBarRootPanelName, Type = typeof(RibbonStackPanel))]
    [TemplatePart(Name = PART_RibbonBarAppMenuName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = PART_HiddenCPName, Type = typeof(ContentPresenter))]
    [TemplatePart(Name=PART_HiddenBarCPName, Type = typeof(ContentPresenter))]
    [TemplatePart(Name = PART_RootName, Type = typeof(Grid))]
    [TemplatePart(Name = PART_RootGridName, Type = typeof(Grid))]
    public partial class RibbonBar : SelectorBase, IRibbonControl
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
        #region Constructors

        /// <summary>
        /// Default static contructor.
        /// </summary>
        static RibbonBar()
        {
            Type ownerType = typeof(RibbonBar);
            RibbonBar.DefaultStyleKeyProperty.OverrideMetadata(ownerType,
                new System.Windows.FrameworkPropertyMetadata(ownerType));

        }

        TranslateTransform transform;

        /// <summary>
        /// Initializes a new instance of the UBCon.Ribbon.RibbonBar class.
        /// </summary>
        public RibbonBar()
            : base()
        {
            Binding binding = new Binding(".")
            {
                RelativeSource = new RelativeSource()
                {
                    Mode = RelativeSourceMode.FindAncestor,
                    AncestorType = typeof(RibbonWindow)
                },
                Mode = BindingMode.OneWay
            };
            BindingOperations.SetBinding
                (
                    this,
                    RibbonBar.OwnerWindowProperty,
                    binding
                );

            RenderTransform = transform = new TranslateTransform();

           // RegisterCommands();

            ContextualItems = new ObservableCollection<ContextualTabItemsGroup>();

            Loaded += OnRibbonBarLoaded;
            
        }

        #endregion

        //------------------------------------------------------
        //
        //  Properties
        //
        //------------------------------------------------------
        #region Properties

        /// <summary>
        /// Gets or sets a boolean value indicating whether the drop-down is open with animation in AutoHide mode.
        /// This is a dependency property.
        /// </summary>
        public bool AnimatedOpen
        {
            get { return (bool)GetValue(AnimatedOpenProperty); }
            set { SetValue(AnimatedOpenProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonBar.AnimatedOpen dependency property.
        /// </summary>
        public static readonly DependencyProperty AnimatedOpenProperty =
            DependencyProperty.Register("AnimatedOpen", typeof(bool), typeof(RibbonBar),
            new PropertyMetadata(false));

        /// <summary>
        /// Gets or sets collection of contextual RibbonTabItem control.
        /// </summary>
        public ObservableCollection<ContextualTabItemsGroup> ContextualItems
        {
            get { return (ObservableCollection<ContextualTabItemsGroup>)GetValue(ContextualItemsProperty); }
            set { SetValue(ContextualItemsProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonBar.ContextualItems dependency property.
        /// </summary>
        public static readonly DependencyProperty ContextualItemsProperty =
            DependencyProperty.Register("ContextualItems", typeof(ObservableCollection<ContextualTabItemsGroup>), 
            typeof(RibbonBar));

        /// <summary>
        /// Checks whether the specified index falls within 0 and Items.Count.
        /// </summary>
        /// <param name="index">Type: System.Int32. The integer value which is checked.</param>
        /// <returns>true if the index falls within the range, false otherwise.</returns>
        internal bool IsValidIndex(int index)
        {
            return index >= 0 && index < Items.Count;
        }

        /// <summary>
        /// Gets or sets owner window of the RibbonBar.
        /// This is a dependency property.
        /// </summary>
        internal RibbonWindow OwnerWindow
        {
            get { return (RibbonWindow)GetValue(OwnerWindowProperty); }
            set { SetValue(OwnerWindowProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonBar.OwnerWindow dependency property.
        /// </summary>
        internal static readonly DependencyProperty OwnerWindowProperty =
            DependencyProperty.Register("OwnerWindow", typeof(RibbonWindow), typeof(RibbonBar), new FrameworkPropertyMetadata(null));

        /// <summary>
        /// Gets or sets a boolean value indicating whether drop-down open or not. 
        /// This is a dependency property.
        /// </summary>
        [Bindable(true),
        Browsable(false),
        ReadOnly(true)]
        public bool IsDropDownOpen
        {
            get { return (bool)GetValue(IsDropDownOpenProperty); }
            set { SetValue(IsDropDownOpenProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonBar.IsDropDownOpen dependency property.
        /// </summary>
        public static readonly DependencyProperty IsDropDownOpenProperty =
            DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(RibbonBar), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(RibbonBar.OnIsDropDownOpenPropertyChanged)));

        /// <summary>
        /// Gets or sets main menu. 
        /// This is a dependency property.
        /// </summary>
        public ApplicationMenu ApplicationMenu
        {
            get { return (ApplicationMenu)GetValue(ApplicationMenuProperty); }
            set { SetValue(ApplicationMenuProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonBar.ApplicationMenu dependency property.
        /// </summary>
        public static readonly DependencyProperty ApplicationMenuProperty =
            DependencyProperty.Register("ApplicationMenu", typeof(ApplicationMenu), typeof(RibbonBar),
            new FrameworkPropertyMetadata((ApplicationMenu)null, 
                new PropertyChangedCallback(OnApplicationMenuChanged)));
        
        /// <summary>
        /// Gets a boolean valude indicating whether contextual item(s) is (are) open.
        /// </summary>
        internal bool ContextualItemsOpen
        {
            get
            {
                return (from c in ContextualItems where c.Visibility == System.Windows.Visibility.Visible select c).Count() > 0;
            }
        }

        /// <summary>
        /// Gets a boolean value which indicates whether auto hide mode can be enabled or not.
        /// </summary>
        internal bool CanEnableAutoHide 
        {
            get 
            {
                return _rootVisual != null &&
                    _rootGrid != null &&
                    _autoHideBarCP != null && 
                    OwnerWindow != null;
            }
        }

        /// <summary>
        /// Gets or sets the value which indicates current state of UBCon.Ribbon.RibbonBar control.
        /// This is a dependency property.
        /// </summary>
        public RibbonBarMode Mode
        {
            get { return (RibbonBarMode)GetValue(ModeProperty); }
            set { SetValue(ModeProperty, value); }
        }

        /// <summary>
        /// Identifies the UBCon.Ribbon.RibbonBar.Mode dependency property.
        /// </summary>
        public static readonly DependencyProperty ModeProperty =
            DependencyProperty.Register("Mode", typeof(RibbonBarMode), typeof(RibbonBar),
            new PropertyMetadata(RibbonBarMode.ShowTabsAndCommands, 
                new PropertyChangedCallback(OnModeChanged)));

        #endregion

        //------------------------------------------------------
        //
        //  Depenency Property Changed Callbacks
        //
        //------------------------------------------------------
        #region Depenency Property Changed Callbacks

        /// <summary>
        /// Invoked when AnimatedOpen property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnAnimatedOpenChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            RibbonBar bar = sender as RibbonBar;
            if (bar.IsLoaded &&
                bar._autoHideGrid != null && 
                bar._autoHideGrid.RenderTransform != null && 
                bar._autoHideGrid.RenderTransform is TranslateTransform)
            {
                
            }
        }

        /// <summary>
        /// Invoked when Mode property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnModeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            RibbonBar bar = sender as RibbonBar;
            RibbonBarMode newValue = (RibbonBarMode)e.NewValue;
            RibbonBarMode oldValue = (RibbonBarMode)e.OldValue;
            
            switch (oldValue)
            {
                case RibbonBarMode.AutoHideMode:
                    bar.DisableAutoHideMode();
                    break;
                case RibbonBarMode.ShowOnlyTabs:
                    bar.DisableShowOnlyTabsMode();
                    break;
            }

            bar.ChangeControlMode(newValue);
        }

        /// <summary>
        /// Changes the current state mode to the specified mode.
        /// </summary>
        private void ChangeControlMode(RibbonBarMode mode) 
        {
            switch (mode)
            {
                case RibbonBarMode.AutoHideMode:

                    if (CanEnableAutoHide)
                    {
                        OwnerWindow.SetValue(RibbonWindow.WindowStateProperty, WindowState.Maximized);
                        EnableAutoHideMode();
                        OwnerWindow.SetValue(RibbonWindow.ModePropertyKey, RibbonBarMode.AutoHideMode);
                    }

                    break;
                case RibbonBarMode.ShowOnlyTabs:

                    if (IsLoaded)
                    {
                        if (OwnerWindow != null)
                        {
                            OwnerWindow.SetValue(RibbonWindow.ModePropertyKey, RibbonBarMode.ShowOnlyTabs);
                        }
                        else 
                        {
                            if (_standartWindow == null) 
                            {
                                _standartWindow = Window.GetWindow(this);
                            }
                            if (_standartWindow != null) 
                            {
                            
                            }
                        }
                        EnableShowOnlyTabsMode();
                    }

                    break;
                case RibbonBarMode.ShowTabsAndCommands:
                    if (OwnerWindow != null)
                    {
                        OwnerWindow.SetValue(RibbonWindow.ModePropertyKey, RibbonBarMode.ShowTabsAndCommands);
                    }
                    if (SelectedItem == null && Items.Count > 0)
                    {
                        SetValue(SelectedIndexProperty, 0);
                    }
                    if (OwnerWindow != null)
                    {
                        OwnerWindow.InvalidateArrange();
                    }
                    break;
            }
        }

        /// <summary>
        /// Invoked when ApplicationMenu property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnApplicationMenuChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        {
            RibbonBar bar = sender as RibbonBar;
            ApplicationMenu menu = e.NewValue as ApplicationMenu;
            if (menu != null) 
            {
                menu._RibbonBar = bar;
            }
        }

        /// <summary>
        /// Invoked when IsDropDownOpenProperty property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        private static void OnIsDropDownOpenPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            bool newValue = (bool)e.NewValue;

            RibbonBar bar = (RibbonBar)sender;

            if (newValue)
            {
                bar._itemsHolder.SetValue(FrameworkElement.WidthProperty, bar.RenderSize.Width - bar._itemsHolder.Margin.Right - bar._itemsHolder.Margin.Left);
                Mouse.Capture(bar, CaptureMode.SubTree);
            }
            else 
            {
                if (bar.Mode == RibbonBarMode.ShowOnlyTabs && 
                    bar.SelectedItem != null)
                {
                    bar.ClearValue(SelectedIndexProperty);
                }
                Mouse.Capture(null);
            }
        }

        /// <summary>
        /// Invoked when ApplicationMenu property changes.
        /// </summary>
        /// <param name="sender">Type: System.Windows.DependencyObject. The DependencyObject on which the property has changed value.</param>
        /// <param name="e">Type: System.Windows.DependencyPropertyChangedEventArgs. Event data that is issued by any event that tracks changes to the effective value of this property.</param>
        //private static void OnApplicationMenuPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
        //{
        
        //}

        #endregion

        //------------------------------------------------------
        //
        //  Overrides
        //
        //------------------------------------------------------
        #region Overrieds

        /// <summary>
        /// Raises SelectionChanged event.
        /// </summary>
        /// <param name="e">Event data for the event.</param>
        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);
            //if (ShowOnlyTabs)
            //{
            //    RibbonTabItem tabItem = SelectedItem as RibbonTabItem;
            //    if (tabItem != null)
            //    {
            //        RibbonTabItemModel model = tabItem.GetValue(RibbonTabItemPanel.RibbonTabItemModelProperty) as RibbonTabItemModel;
            //        if (model != null)
            //        {
            //            Point p = tabItem.TranslatePoint(RibbonHelper.emptyPoint, this);
            //            UpdateHiddenRectangle(p.X, tabItem.RenderSize.Width);
            //        }
            //    }
            //}
        }

        /// <summary>
        /// Rearranges and resizes hidden rectangle with specified location and width.
        /// </summary>
        /// <param name="xPosition">Type: System.Double</param>
        /// <param name="renderWidth">Type: System.Double</param>
        internal void UpdateHiddenRectangle(double xPosition, double renderWidth) 
        {
            //Canvas.SetLeft(_hiddenRect, xPosition);
            //_hiddenRect.Width = renderWidth;
            //Canvas.SetTop(_hiddenRect, -9);
        }

        /// <summary>
        /// Invoked when an unhandled Mouse.LostMouseCapture attached event reaches an element in its route that is derived from this class. 
        /// </summary>
        /// <param name="e">Event data for the event </param>
        protected override void OnLostMouseCapture(MouseEventArgs e)
        {
            e.Handled = true;
            
            base.OnLostMouseCapture(e);

            //if (ShowOnlyTabs && IsDropDownOpen)
            //{
            //    Visual visual = e.MouseDevice.Captured as Visual;
            //    bool shouldResetCapture = UBCon.Core.NativeMethods.GetCapture() != IntPtr.Zero;
            //    if (shouldResetCapture)
            //    {
            //        //Mouse.Capture(this,  CaptureMode.SubTree);
            //    }
            //    else 
            //    {
            //        SetValue(IsDropDownOpenProperty, false);
            //    }
            //}
        }

        /// <summary>
        /// Called when the ItemsSource property changes.
        /// </summary>
        /// <param name="oldValue">Old value of the ItemsSource property.</param>
        /// <param name="newValue">New value of the ItemsSource property.</param>
        protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
        {
            base.OnItemsSourceChanged(oldValue, newValue);

            if (newValue != null)
            {
                throw new InvalidOperationException("RibbonBar does not support ItemsSource");
            }
        }

        /// <summary>
        /// Creates or identifies the element used to display a specified item. 
        /// (Overrides ItemsControl.GetContainerForItemOverride().)
        /// </summary>
        /// <returns></returns>
        protected override DependencyObject GetContainerForItemOverride()
        {
            return new RibbonTabItem();
        }

        /// <summary>
        /// Determines if the specified item is (or is eligible to be) its own ItemContainer. 
        /// (Overrides ItemsControl.IsItemItsOwnContainerOverride(Object).)
        /// </summary>
        /// <param name="item">Specified item.</param>
        /// <returns>true if the item is its own ItemContainer; otherwise, false.</returns>
        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is RibbonTabItem;
        }

        //private Border SelectedItemsBorder;

        /// <summary>
        /// Invoked whenever application code or internal processes (such as a rebuilding layout pass) call ApplyTemplate. 
        /// In simplest terms, this means the method is called just before a UI element displays in  app.  
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            itemsHost = GetTemplateChild(PART_RibbonBarRootPanelName) as RibbonTabItemPanel;

            //SelectedItemsBorder = GetTemplateChild("SelectedItemsBorder") as Border;

            _rootGrid = GetTemplateChild(PART_RootGridName) as Grid;

            _rootVisual = GetTemplateChild(PART_RootName) as Grid;

            _hiddenCP = GetTemplateChild(PART_HiddenCPName) as ContentPresenter;

            _itemsHolder = GetTemplateChild(PART_ItemsHolderName) as Border;

            _autoHideBarCP = GetTemplateChild(PART_HiddenBarCPName) as ContentPresenter;

            _autoHideGrid = GetTemplateChild(PART_AutoHideGridName) as Grid;
            //_hiddenRect = GetTemplateChild(PART_HiddenRectName) as FrameworkElement;
            if (_rootGrid == null ||
                _hiddenCP == null ||
                _itemsHolder == null/* || 
                _hiddenRect == null*/||
                _rootVisual == null ||
                _autoHideBarCP == null || _autoHideGrid==null)
            {
                throw new NullReferenceException(PART_RootGridName + " " + PART_HiddenCPName + " " + PART_ItemsHolderName);
            }

            if (hiddenPanel != null)
            {
                hiddenPanel.Children.Clear();
            }
            
            hiddenPanel = GetTemplateChild(PART_ContextualHiddenPanelName) as Canvas;

            if (_autoHidepopup != null) 
            {
                _autoHidepopup.Closed -= OnAutoHidePopupClosed;
            }
            _autoHidepopup = GetTemplateChild(PART_AutoHidePopupName) as Popup;

            if (_autoHidepopup != null && _autoHidepopup.Child != null) 
            {
                _autoHidepopup.Child.RenderTransform = new TranslateTransform();
                _autoHidepopup.Closed += OnAutoHidePopupClosed;
            }
            if (_dropDownMenuPopup != null) 
            {
                _dropDownMenuPopup.Closed -= OnMenuPopupClosed;
            }
            _dropDownMenuPopup = GetTemplateChild(PART_DropDownMenuPopupName) as Popup;
            
            if (_dropDownMenuPopup != null) 
            {
                _dropDownMenuPopup.Closed += OnMenuPopupClosed;
            }
            
            AppMenuButton = GetTemplateChild(PART_RibbonBarAppMenuName) as ToggleButton;
            if (AppMenuButton != null && ApplicationMenu != null)
            {
                //AppMenuButton.Checked += OnAppMenuButtonChecked;
                BindingOperations.SetBinding
                    (
                        AppMenuButton,
                        ToggleButton.IsCheckedProperty,
                        new Binding("ApplicationMenu.IsApplicationMenuOpen") 
                        { 
                            Source = this, 
                            Mode = BindingMode.TwoWay 
                        }
                    );
            }
        }
      

        /// <summary>
        /// Raises the Initialized event. This method is invoked whenever IsInitialized is set to true.
        /// </summary>
        /// <param name="e">Type: System.EventArgs. Event data for the event.</param>
        protected override void OnInitialized(EventArgs e)
        {
            RibbonWindow rwindow = RibbonHelper.GetWindow(this);

            if (rwindow != null)
            {
                rwindow.InternalRibbonBar = this;

                OwnerWindow = rwindow;

                BindingOperations.SetBinding
                    (
                        rwindow,
                        RibbonWindow.ApplicationMenuProperty,
                        new Binding("ApplicationMenu")
                        {
                            Source = this,
                            Mode = BindingMode.OneWay
                        }
                    );
                if (rwindow.QAToolbar != null) 
                {
                    rwindow.QAToolbar.SetValue(QAToolbar.IsAboveRibbonProperty, true);
                }
            }
            base.OnInitialized(e);
        }

        #endregion

        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
        #region Private Methods

        /// <summary>
        /// Disables ShowOnlyTabs mode and restores default of the control.
        /// </summary>
        private void DisableShowOnlyTabsMode()
        {
            RearrengeItemsPresenter(true);
            Mouse.RemovePreviewMouseDownOutsideCapturedElementHandler(this, OnPreviewMouseDownOutsideCapturedElementCaptured);
            _itemsHolder.SetValue(FrameworkElement.WidthProperty, double.NaN);
            Mouse.Capture(null);
        }

        /// <summary>
        /// Changes from default state to ShowOnlyTabs mode.
        /// </summary>
        private void EnableShowOnlyTabsMode()
        {
            RearrengeItemsPresenter();
            Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnPreviewMouseDownOutsideCapturedElementCaptured);
            SetValue(IsDropDownOpenProperty, false);
            ClearValue(SelectedIndexProperty);
        }

        /// <summary>
        /// Performs necessary logic in order to enable auto hide mode for the control.
        /// </summary>
        private void EnableAutoHideMode() 
        {
            if (OwnerWindow != null)
            {
                tempItems.Clear();
                RibbonWindow window = OwnerWindow;
                foreach (UIElement item in window.rootPanel.Children)
                {
                    if (Grid.GetRow(item) == 0 &&
                        item != window.showHiddenBar &&
                        item != window.hiddenItemsPanel)
                    {
                        tempItems.Add(item);
                    }
                }
                foreach (UIElement item in tempItems)
                {
                    window.rootPanel.Children.Remove(item);
                    _autoHideGrid.Children.Add(item);
                }

                _rootVisual.Children.Remove(_rootGrid);
                _rootVisual.Children.Remove(_dropDownMenuPopup);
                _autoHideGrid.Children.Add(_dropDownMenuPopup);
                _autoHideBarCP.SetValue(ContentPresenter.ContentProperty, _rootGrid);

                HideRibbonBar();
            }
        }

        /// <summary>
        /// Performs necessary logic in order to disable auto hide mode for the control.
        /// </summary>
        private void DisableAutoHideMode() 
        {
            if (OwnerWindow != null)
            {
                
                _autoHideGrid.Children.Remove(_dropDownMenuPopup);
                foreach (UIElement item in tempItems)
                {
                    _autoHideGrid.Children.Remove(item);
                    OwnerWindow.rootPanel.Children.Add(item);
                }
                tempItems.Clear();
                _autoHideBarCP.ClearValue(ContentPresenter.ContentProperty);

                _rootVisual.Children.Add(_rootGrid);
                _rootVisual.Children.Add(_dropDownMenuPopup);
            }
        }

        /// <summary>
        /// Removes root ItemsPresenter from the root grid and inserts into hidden 
        /// grid and vice-versa if isRollback is true.
        /// </summary>
        private void RearrengeItemsPresenter(bool isRollback=false) 
        {
            if (isRollback)
            {
                _hiddenCP.ClearValue(ContentPresenter.ContentProperty);
                //_hiddenGrid.Children.Remove(_itemsHolder);
                _rootGrid.Children.Add(_itemsHolder);
                _itemsHolder.Width = double.NaN;
            }
            else
            {
                _rootGrid.Children.Remove(_itemsHolder);
                _hiddenCP.SetValue(ContentPresenter.ContentProperty, _itemsHolder);
                //_hiddenGrid.Children.Add(_itemsHolder);

            }
        }

        /// <summary>
        /// Registers commands.
        /// </summary>
        private void RegisterCommands()
        {
        }

        #endregion

        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
        #region Internal Methods

        /// <summary>
        /// Sets content of menu popup.
        /// </summary>
        internal void AddChildToMenuPopup(FrameworkElement element) 
        {
            if (_dropDownMenuPopup != null) 
            {
                _dropDownMenuPopup.SetValue(Popup.ChildProperty, element);
               
            }
        }

        /// <summary>
        /// Clears content of menu popup.
        /// </summary>
        internal void RemoveChildFromMenuPopup() 
        {
            if (_dropDownMenuPopup != null) 
            {
                _dropDownMenuPopup.ClearValue(Popup.ChildProperty);
            }
        }

        /// <summary>
        /// Shows hidden popup.
        /// </summary>
        internal void ShowHiddenBar() 
        {
            if (_autoHidepopup != null) 
            {
                _autoHideGrid.SetValue(FrameworkElement.WidthProperty, RenderSize.Width - _itemsHolder.Margin.Right - _itemsHolder.Margin.Left);
                _autoHidepopup.SetValue(Popup.IsOpenProperty, true);
                if (AnimatedOpen && _autoHidepopup.Child!=null) 
                {
                    TranslateTransform translate = _autoHidepopup.Child.RenderTransform as TranslateTransform;
                    if (translate != null)
                    {
                        translate.Y = -45.0D;
                        if (_showHiddenBarAnimation == null)
                        {
                            _showHiddenBarAnimation = new Storyboard();
                            DoubleAnimation doubleAnimation = new DoubleAnimation()
                            {
                                EasingFunction = new ExponentialEase()
                                {
                                    EasingMode = EasingMode.EaseOut,
                                    Exponent = 5
                                },
                                From = -45.0D,
                                To = 0.0D,
                                Duration=new Duration(TimeSpan.FromSeconds(0.3))
                            };
                            Storyboard.SetTarget(doubleAnimation, _autoHidepopup.Child);
                            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(Constants.YPropertyPath));
                            _showHiddenBarAnimation.Children.Add(doubleAnimation);
                        }
                        _showHiddenBarAnimation.Begin();
                    }
                }
            }
        }

        /// <summary>
        /// Closes hidden popup.
        /// </summary>
        internal void HideRibbonBar() 
        {
            if (_autoHidepopup != null)
            {
                _autoHidepopup.SetValue(Popup.IsOpenProperty, false);
            }
        }

        /// <summary>
        /// Calculates avaliable space where caption's text is located.
        /// </summary>
        internal void GetContextualLocations(ref double beginPoint, ref double endPoint)
        {
            bool isFirst = true;
            int count = Items.Count;
            RibbonTabItemModel model = null;
            for (int i = 0; i < count; i++)
            {
                RibbonTabItem tabItem = ItemContainerGenerator.ContainerFromItem(Items[i]) as RibbonTabItem;
                if (tabItem != null &&
                    tabItem.IsContextual)
                {
                    if (isFirst)
                    {
                        isFirst = false;
                        model = tabItem.GetValue(RibbonTabItemPanel.RibbonTabItemModelProperty) as RibbonTabItemModel;
                        if (model != null)
                        {
                            beginPoint = model.WindowRelativePosX;
                            endPoint = beginPoint;
                        }
                    }
                    endPoint += tabItem.ActualWidth;
                }
            }

        }

        /// <summary>
        /// Adds the specified control to Items.
        /// </summary>
        /// <param name="item">The control that is added.</param>
        internal void AddNewItem(RibbonTabItem item)
        {
            if (hiddenPanel != null && hiddenPanel.Children.Contains(item))
            {
                hiddenPanel.Children.Remove(item);
            }

            Items.Add(item);
        }

        /// <summary>
        /// Places QAToolbar above the RibbonBar if isAbove parameter's value is true, below otherwise.
        /// </summary>
        internal void RearrangeQAToolbar(bool isAbove = false)
        {
            if (OwnerWindow != null)
            {
                RibbonWindow window = OwnerWindow;
                Grid grid = Mode != RibbonBarMode.AutoHideMode ? window.rootPanel : _autoHideGrid;
                ContentPresenter qaPresenter = window.QAToolbarPresenter;
                if (isAbove)
                {
                    
                    _rootGrid.Children.Remove(qaPresenter);
                    Grid.SetRow(qaPresenter, 0);
                    Grid.SetColumn(qaPresenter, 1);
                    Grid.SetColumnSpan(qaPresenter, 1);
                    grid.Children.Add(qaPresenter);
                    if (tempItems.Count > 0 &&
                        !tempItems.Contains(qaPresenter))
                    {
                        tempItems.Insert(1, qaPresenter);
                    }
                }
                else
                {
                    grid.Children.Remove(qaPresenter);
                    Grid.SetRow(qaPresenter, 2);
                    Grid.SetColumnSpan(qaPresenter, 3);
                    Grid.SetColumn(qaPresenter, 0);
                    _rootGrid.Children.Add(qaPresenter);
                    tempItems.Remove(qaPresenter);
                }
            }
        }

        #endregion

        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------
        #region Public Methods
        #endregion

        //------------------------------------------------------
        //
        //  Event Handlers
        //
        //------------------------------------------------------
        #region Event Handlers

        private void OnAutoHidePopupClosed(object sender, EventArgs e)
        {
            if (AppMenuButton != null && AppMenuButton.IsChecked == true)
            {
                AppMenuButton.SetValue(ToggleButton.IsCheckedProperty, false);
            }
        }

        /// <summary>
        /// Occurs when application menu button is checked.
        /// </summary>
        private void OnAppMenuButtonChecked(object sender, RoutedEventArgs e) 
        {
            if (OwnerWindow == null&&_dropDownMenuPopup!=null) 
            {
                _dropDownMenuPopup.SetValue(Popup.IsOpenProperty, true);
            }
        }

        /// <summary>
        /// Occurs when menu popup is closed.
        /// </summary>
        /// <param name="sender">Owner of the event.</param>
        /// <param name="e">Event data for the event.</param>
        private void OnMenuPopupClosed(object sender, EventArgs e)
        {
            if (AppMenuButton != null && AppMenuButton.IsChecked == true) 
            {
                AppMenuButton.SetValue(ToggleButton.IsCheckedProperty, false);
            }
        }

        /// <summary>
        /// Occurs when the primary mouse button is pressed outside the element that is capturing mouse events.
        /// </summary>
        /// <param name="sender">Owner of the event.</param>
        /// <param name="e">Event data for the event.</param>
        private void OnPreviewMouseDownOutsideCapturedElementCaptured(object sender, MouseButtonEventArgs e) 
        {
            SetValue(IsDropDownOpenProperty, false);
        }

        /// <summary>
        /// Occurs when the element is laid out, rendered, and ready for interaction. 
        /// (Inherited from FrameworkElement.)
        /// </summary>
        /// <param name="sender">Owner of the event.</param>
        /// <param name="e">Event data for the event.</param>
        private void OnRibbonBarLoaded(object sender, RoutedEventArgs e)
        {
            if (hiddenPanel != null)
            {
                foreach (ContextualTabItemsGroup group in ContextualItems)
                {
                    if (!hiddenPanel.Children.Contains(group))
                    {
                        hiddenPanel.Children.Add(group);
                        foreach (RibbonTabItem tabItem in group.Items)
                        {
                            hiddenPanel.Children.Add(tabItem);
                        }
                    }
                }
            }

            if (OwnerWindow == null) 
            {
                if (_dropDownMenuPopup != null) 
                {
                    ContentPresenter menuPresenter = new ContentPresenter();
                    BindingOperations.SetBinding
                        (
                            menuPresenter,
                            ContentPresenter.ContentProperty,
                            new Binding("ApplicationMenu") { Source = this, Mode = BindingMode.TwoWay }
                        );
                    _dropDownMenuPopup.SetValue(Popup.ChildProperty, menuPresenter);


                }
            }
        }

        #endregion

        //------------------------------------------------------
        //
        //  Fields
        //
        //------------------------------------------------------
        #region Fields

        private const string PART_RootGridName = "PART_RootGrid",
                             PART_RibbonBarRootPanelName = "PART_RibbonBarRootPanel",
                             PART_RibbonBarAppMenuName = "PART_RibbonBarAppMenu",
                             PART_ContextualHiddenPanelName = "PART_ContextualHiddenPanel",
                             PART_HiddenCPName = "PART_HiddenCP",
                             PART_ItemsHolderName = "PART_ItemsHolder",
                             PART_HiddenBarCPName = "PART_HiddenBarCP",
                             PART_RootName = "PART_Root",
                             PART_AutoHidePopupName = "PART_AutoHidePopup",
                             PART_AutoHideGridName = "PART_AutoHideGrid",
                             PART_DropDownMenuPopupName = "PART_DropDownMenuPopup";//,
                             //PART_HiddenRectName = "PART_HiddenRect";
        private RibbonTabItemPanel itemsHost = null;
        //private Storyboard showSelectedItemsAnimation, closeSelectedItemsAnimation;
        internal Grid _rootGrid, _rootVisual, _autoHideGrid;
        private ContentPresenter _hiddenCP, _autoHideBarCP;
        private Canvas hiddenPanel;
        private Border _itemsHolder = null;
        internal Popup _autoHidepopup = null;
        private List<UIElement> tempItems = new List<UIElement>();
        private Storyboard _showHiddenBarAnimation;
        internal Popup _dropDownMenuPopup;
        internal ToggleButton AppMenuButton;
        private Window _standartWindow;
        //internal FrameworkElement _hiddenRect;
        #endregion

        //------------------------------------------------------
        //
        //  IRibbonControl Implementation
        //
        //------------------------------------------------------
        #region IRibbonControl Implementation

        /// <summary>
        /// Gets a boolean value indicating whether the contol's size is large
        /// </summary>
        public bool IsLarge
        {
            get { return true; }
        }

        #endregion
    }
}
